package com.suray.wcs.service.init;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.suray.basic.wcs.path.core.Node;
import com.suray.basic.wcs.plc.entity.PlcDeviceDB;
import com.suray.basic.wcs.plc.enums.Location;
import com.suray.basic.wcs.plc.enums.PlcDeviceType;
import com.suray.basic.wcs.plc.pojo.DeviceBase;
import com.suray.basic.wcs.plc.pojo.lifter.data.map.CarMap;
import com.suray.basic.wcs.plc.pojo.lifter.data.map.LifterMap;
import com.suray.basic.wcs.plc.pojo.lifter.data.map.PalletMap;
import com.suray.basic.wcs.plc.service.impl.PlcDeviceDBServiceImpl;
import com.suray.basic.wcs.plc.utils.PalletStatus;
import com.suray.basic.wcs.utils.Coord;
import com.suray.basic.wcs.utils.LoggerUtil;
import com.suray.basic.wcs.utils.WcsFuncUtil;
import com.suray.commin.core.utils.SpringContextHolder;
import com.suray.commin.enmus.DeviceStatus;
import com.suray.wcs.service.scheduling.PlcReadTimer;
import com.suray.wcs.service.system.entity.PlcDB;
import com.suray.wcs.service.system.service.impl.PlcDBServiceImpl;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@Component
public class PlcInit {

    private final static LifterInfoFunc lifterInfoFunc = SpringContextHolder.getBean(LifterInfoFunc.class);

    private static void refresh() {
        PlcDBServiceImpl plcDbService = SpringContextHolder.getBean(PlcDBServiceImpl.class);
        List<PlcDB> plcList = plcDbService.list();
        for (PlcDB plcModel : plcList) {
            try {
                if (!plcModel.getStatus().equals(DeviceStatus.DISABLE.getCode())) {
                    reloadDeviceByPlc(plcModel);
                }
            } catch (Exception e) {
                LoggerUtil.warn("Plc初始化失败:" + plcModel.getPlcName(), PlcInit.class);
                WcsFuncUtil.exceptionLog(e, PlcInit.class);
            }
        }
    }

    private static void reloadDeviceByPlc(PlcDB plcModel) {
        PlcDeviceDBServiceImpl plcDeviceDBService = SpringContextHolder.getBean(PlcDeviceDBServiceImpl.class);
        List<PlcDeviceDB> plcDeviceDB = plcDeviceDBService.list(new QueryWrapper<PlcDeviceDB>().lambda().eq(PlcDeviceDB::getPlcId, plcModel.getPlcId()));
        List<DeviceBase> deviceBases = new ArrayList<>();
        for (PlcDeviceDB db : plcDeviceDB) {
            Location location = db.getLocation() == null ? null : Location.parseLocationCode(db.getLocation());
            DeviceBase deviceBase = new DeviceBase(PlcDeviceType.parsePlcDeviceType(db.getDeviceType()), db.getStartAddress(), db.getDeviceName(),
                    db.getDeviceNo(), new Coord(Node.parseGrid(db.getDeviceLocation())), location,
                    new Coord(Node.parseGrid(db.getPlcLockLocation())), db.getDeviceId(), db.getGridzMax(),
                    db.getGridzRelative(), plcModel.getPlcId());
            // 货叉提升机读取提升机的位移量信息
            if (db.getDeviceType().equals(PlcDeviceType.FORK_LIFTER.getTypeNum())) {
                refreshLifterInfo(deviceBase);
            }
            deviceBases.add(deviceBase);
        }
        new PlcReadTimer(plcModel, deviceBases).start();
    }

    /**
     * 加载货叉提升机的提升机层位移量
     *
     * @param series
     * @return
     */
    private static Map<Integer, LifterMap> analyzLifterDis(String series) {
        Map<Integer, LifterMap> lifterLayerMap = new HashMap<>();
        lifterInfoFunc.getLifterInfos(series).forEach(lifterMap -> lifterLayerMap.put(lifterMap.layer, lifterMap));
        return lifterLayerMap;
    }

    /**
     * 加载货叉提升机的两向车行驶的位移量
     *
     * @param series
     * @return
     */
    private static Map<Coord, CarMap> analyzeCarDis(String series) {
        Map<Coord, CarMap> carLocationMap = new HashMap<>();

        lifterInfoFunc.getCarInfos(series).forEach(carMap -> carLocationMap.put(carMap.node, carMap));
        return carLocationMap;
    }

    /**
     * 加载货叉提升机的两向车托盘升降的位移量
     *
     * @param series
     * @return
     */
    private static Map<PalletStatus, PalletMap> analyzePalletDis(String series) {
        Map<PalletStatus, PalletMap> palletStatusMap = new HashMap<>();

        lifterInfoFunc.getPalletInfos(series).forEach(palletMap -> palletStatusMap.put(palletMap.palletStatus, palletMap));
        return palletStatusMap;
    }

    public static void refreshLifterInfo(DeviceBase deviceBase) {
        deviceBase.setLifterLayerMap(analyzLifterDis(deviceBase.getSeries()));
        deviceBase.setCarLocationMap(analyzeCarDis(deviceBase.getSeries()));
        deviceBase.setPalletStatusMap(analyzePalletDis(deviceBase.getSeries()));
    }

    @PostConstruct
    public static void init() {
        refresh();
    }
}
